/**
 * @file AudioCapture.c
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2022-08-09
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include <stdio.h>
#include <string.h>

#include "ak_common.h"
#include "ak_log.h"
#include "ak_ai.h"

#include "AudioCapture.h"

/************************* Define ******************************/
#define PCM_FILE_PATH  "/mnt/Audio_Capture/AudioStream.pcm"

#define SAMPLE_RATE 16000
#define AUDIO_CHANNEL_NUM   1
#define DEVICE_ID   DEV_ADC
#define BUFFER_NUM 1024
#define MAX_FILE_NUM    4
#define MAX_DATA_PER_FILE 8000

/*********************** Variable ******************************/
int AiHandleID = -1;
int DataCount = 0;
int CurFileNum = 0;
char RecordFilePath[40] = "/mnt/Audio_Capture/AudioStream0.pcm";
struct frame ai_frame = {0};

int AudioCaptureInit(void)
{
    int ret = -1;
    
    /* open ai device */
    struct ak_audio_in_param param;
    memset(&param, 0, sizeof(struct ak_audio_in_param));
    param.pcm_data_attr.sample_rate = SAMPLE_RATE;                // set sample rate
    param.pcm_data_attr.sample_bits = AK_AUDIO_SMPLE_BIT_16;    // sample bits only support 16 bit
    param.pcm_data_attr.channel_num = AUDIO_CHANNEL_NUM;    // channel number
    param.dev_id = DEVICE_ID;//DEV_ADC;
    if (ak_ai_open(&param, &AiHandleID))
    {
        ak_print_normal(MODULE_ID_APP, "*** ak_ai_open failed. ***\n");
        return -1;
    }
        
    /* set attr */
    ret = ak_ai_set_source(AiHandleID, AI_SOURCE_MIC);
    ret = ak_ai_set_gain(AiHandleID, 5);    
    struct ak_audio_nr_attr     default_ai_nr_attr      = {-40, 0, 1};
    ret = ak_ai_set_nr_attr(AiHandleID, &default_ai_nr_attr);
    struct ak_audio_agc_attr    default_ai_agc_attr     = {24576, 4, 0, 80, 0, 1};
    ret = ak_ai_set_agc_attr(AiHandleID, &default_ai_agc_attr);
    ret = ak_ai_set_volume(AiHandleID, 5);

    /* start capture */
    ret = ak_ai_start_capture(AiHandleID);
    if (ret)
    {
        ak_print_error(MODULE_ID_APP, "*** ak_ai_start_capture failed. ***\n");
        ak_ai_close(AiHandleID);
        return -1;
    }

    /* 删除临时文件 */
    int i = 0;
    char path[40] = {0};
    for(i=0;i<MAX_FILE_NUM;i++)
    {
        sprintf(path, "/mnt/Audio_Capture/AudioStream%d.pcm", i);
        remove(path);
    }

    return 0;
}

int AudioRecord(void)
{
    FILE *PcmFp;
    int ret = -1;

    ret = ak_ai_get_frame(AiHandleID, &ai_frame, 0);
    if(ret)
    {
        return -1;
    }
    if (!ai_frame.data || ai_frame.len <= 0)
    {
        ak_print_error(MODULE_ID_APP, "get frame error.\n");
        return -1;
    }

    PcmFp = fopen(RecordFilePath, "ab");
    // fseek(PcmFp, 0, SEEK_END);
    if (NULL == PcmFp)
    {
        perror("open pcm");
        return -1;
    }

    /* write a frame to pcm file */
    if(fwrite(ai_frame.data, ai_frame.len, 1, PcmFp) < 0)
    {
        ak_print_error(MODULE_ID_APP, "write file error.\n");
        fclose(PcmFp);
        return -1;
    }
    fclose(PcmFp);

    DataCount += ai_frame.len/2;
    printf("%d\n", DataCount);

    ak_ai_release_frame(AiHandleID, &ai_frame);


    return 0;
}

int AudioFileProcess(void)
{
    if(DataCount > MAX_DATA_PER_FILE)   //8000个数据
    {
        printf("file %d\n", CurFileNum);
        /* reset frame count */
        DataCount = 0;

        char curFilePath[40];
        FILE *output_fp;
        FILE *cur_fp;

        /* remove last output file */
        if(remove(OUTPUT_FILE_PATH))
        {
            perror("remove");
        }

        /* create new output file */
        output_fp = fopen(OUTPUT_FILE_PATH, "wb");
        if(output_fp == NULL)
        {
            perror("open pcm file");
            return -1;
        }

        int i = 0;
        char readBuffer[MAX_DATA_PER_FILE*2 + 2048]; //留2048字节的阈值

        /*假设现在CurFileNum为4，则先将5-9号的文件组合起来，放到最前面*/
        for(i=CurFileNum+1;i<MAX_FILE_NUM;i++)
        {
            sprintf(curFilePath, "/mnt/Audio_Capture/AudioStream%d.pcm", i);
            cur_fp = fopen(curFilePath, "rb");
            if(cur_fp == NULL)
            {
                // printf("%s do not exit\n", curFilePath);
                continue;
            }

            int ret_len = fread(readBuffer, 2, MAX_DATA_PER_FILE+1024, cur_fp);
            if(ret_len < 0)
            {
                perror(curFilePath);
                fclose(output_fp);
                fclose(cur_fp);
                return -1;
            }
            fclose(cur_fp);

            ret_len = fwrite(readBuffer, 2, ret_len, output_fp);
            if(ret_len < 0)
            {
                perror("write file");
                fclose(output_fp);
                return -1;
            }
        }

        /*再将0-4号的文件组合起来加到文件末尾*/
        for(i=0;i<CurFileNum+1;i++)
        {
            sprintf(curFilePath, "/mnt/Audio_Capture/AudioStream%d.pcm", i);
            cur_fp = fopen(curFilePath, "rb");
            if(cur_fp == NULL)
            {
                printf("%s do not exit\n", curFilePath);
                continue;
            }

            int ret_len = fread(readBuffer, 2, MAX_DATA_PER_FILE+1024, cur_fp);
            if(ret_len < 0)
            {
                perror(curFilePath);
                fclose(output_fp);
                fclose(cur_fp);
                return -1;
            }
            fclose(cur_fp);

            ret_len = fwrite(readBuffer, 2, ret_len, output_fp);
            if(ret_len < 0)
            {
                perror("write file");
                fclose(output_fp);
                return -1;
            }
        }

        fclose(output_fp);


        /* process the file num */
        if(++CurFileNum >= MAX_FILE_NUM)
        {CurFileNum = 0;}

        sprintf(RecordFilePath, "/mnt/Audio_Capture/AudioStream%d.pcm", CurFileNum);
        if(remove(RecordFilePath) < 0)
        {
            perror("remove file");
        }

        printf("e\n");
        return 0;
    }
    
    return -1;
}

int AudioCaptureDeinit(void)
{ 
    int ret = -1;
    ret = ak_ai_stop_capture(AiHandleID);
    if (ret)
    {
        ak_print_error(MODULE_ID_APP, "*** ak_ai_stop_capture failed. ***\n");
        ak_ai_close(AiHandleID);
        return -1;
    }

    ak_ai_close(AiHandleID);

    return 0;
}